import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flustars/flustars.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_web_2021/utils/toast/OkToastUtil.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

import '../../Include.dart';
import 'BaseEntity.dart';
import 'BaseListEntity.dart';
import 'ErrorEntity.dart';
import 'NWMethod.dart';

///// 返回 LoginEntity
// DioManager().request<LoginEntity>(
//   NWMethod.POST,
//   NWApi.loginPath,
//   params: {"account": "421789838@qq.com", "password": "123456"},
//   success: (data) {
//       print("success data = $data"});
//   }, error: (error) {
//       print("error code = ${error.code}, massage = ${error.message}");
//   }
// );
//
// // 返回 List<LoginEntity>
// DioManager().requestList<LoginEntity>(
//   NWMethod.POST,
//   NWApi.queryListJsonPath,
//   params: {"account": "421789838@qq.com", "password": "123456"},
//   success: (data) {
//       print("success data = $data"});
//   }, error: (error) {
//       print("error code = ${error.code}, massage = ${error.message}");
//   }
// );
class DioManager {
  static final DioManager _shared = DioManager._internal();

  factory DioManager() => _shared;
  Dio dio;

  DioManager._internal() {
    if (dio == null) {
      BaseOptions options = BaseOptions(
        baseUrl: NWApi.baseApi,
        contentType: Headers.jsonContentType,
        responseType: ResponseType.plain,
        //responseType: ResponseType.json,
        receiveDataWhenStatusError: false,
        connectTimeout: 15000,
        receiveTimeout: 15000,
      );
      dio = Dio(options);
      if (Config.ENVIRONMENT_TYPE!=Environment.production) {
        dio.interceptors.add(PrettyDioLogger(
          requestHeader: kDebugMode,
          requestBody: kDebugMode,
          responseBody: kDebugMode,
          responseHeader: kDebugMode,
          compact: kDebugMode,
        ));
      }
    }

  }

  // 请求，返回参数为 T
  // method：请求方法，NWMethod.POST等
  // path：请求地址
  // params：请求参数
  // success：请求成功回调
  // error：请求失败回调
  Future request<T>(NWMethod method, String path,
      {Map<String, dynamic> params,
      Function(T) success,
      Function(ErrorEntity) error}) async {
    try {
      Response response = await dio.request(path,
          queryParameters: params,
          options: Options(method: NWMethodValues[method]));

      // Log().info("adfsa-------------------------sad-------------------------addd-----|"
      //     "\n ${response.data.toString()}"
      //     "\n ${response.data.runtimeType}"
      //     "|------->");

      if (response != null) {
        try {
          Map<String, dynamic> responseData = jsonDecode(response.data);

          BaseEntity entity = BaseEntity<T>.fromJson(responseData);
          if (entity.code == 0) {
            success(entity.data);
          } else if(entity.code == 999){
            success(entity.data);
          } else{
            error(ErrorEntity(code: entity.code, message: entity.message));
          }
        }catch(e){
          error(ErrorEntity(code: -1, message:response.data.toString()));
        }

      } else {
        error(ErrorEntity(code: -1, message: "未知错误"));
      }
    } on DioError catch (e) {
      error(createErrorEntity(e));

    }
  }

  // 请求，返回参数为 List<T>
  // method：请求方法，NWMethod.POST等
  // path：请求地址
  // params：请求参数
  // success：请求成功回调
  // error：请求失败回调
  Future requestList<T>(NWMethod method, String path,
      {Map<String, dynamic> params,
      Function(List<T>) success,
      Function(ErrorEntity) error}) async {
    try {
      Response response = await dio.request(path,
          queryParameters: params,
          options: Options(method: NWMethodValues[method]));
      if (response != null) {
        Map<String, dynamic> responseData = jsonDecode(response.data);
        BaseListEntity entity = BaseListEntity<T>.fromJson(responseData);
        if (entity.code == 0) {
          success(entity.data);
        } else if(entity.code == 999){
          success(entity.data);
        } else{
          error(ErrorEntity(code: entity.code, message: entity.message));
        }
      } else {
        error(ErrorEntity(code: -1, message: "未知错误"));
      }
    } on DioError catch (e) {
      error(createErrorEntity(e));
    }
  }


  // 请求，返回参数为 T
  // method：请求方法，NWMethod.POST等
  // path：请求地址
  // params：请求参数
  // success：请求成功回调
  // error：请求失败回调
  Future requestUploadImgOne<T>(NWMethod method, String path,
      {FormData params,bool isShowProgressDialog=true,

        Function(T) success,

        Function(ErrorEntity) error}) async {
    try {
      var option = Options(method: "POST", contentType: "multipart/form-data");//上传文件的content-type 表单
      Response response = await dio.post(
        path,
        data: params,
        options: option,
        onSendProgress: (int sent, int total) {
          Log().info("上传进度：" +
              NumUtil.getNumByValueDouble(sent / total * 100, 2)
                  .toStringAsFixed(2) +
              "%"); //取精度，如：56.45%
        },
      );
      if (response != null) {
        BaseEntity entity = BaseEntity<T>.fromJson(response.data);
        if (entity.code == 0) {
          success(entity.data);
        } else if(entity.code == 999){
          success(entity.data);
        } else{
          error(ErrorEntity(code: entity.code, message: entity.message));
        }
      } else {
        error(ErrorEntity(code: -1, message: "未知错误"));
      }
    } on DioError catch (e) {
      error(createErrorEntity(e));
    }
  }



  // 错误信息
  ErrorEntity createErrorEntity(DioError error) {
    if (error.type == DioErrorType.DEFAULT ||
        error.type == DioErrorType.RESPONSE) {
      if (error is SocketException) {
        return ErrorEntity(code: -1, message: "网络异常，请检查你的网络！");
      }
      if (error is HttpException) {
        return ErrorEntity(code: -1, message: "服务器异常！");
      }
      return ErrorEntity(code: -1, message: "网络异常，请检查你的网络！");
    } else {
      switch (error.type) {
        case DioErrorType.CANCEL:
          {
            return ErrorEntity(code: -1, message: "请求取消");
          }
          break;
        case DioErrorType.CONNECT_TIMEOUT:
          {
            return ErrorEntity(code: -1, message: "连接超时");
          }
          break;
        case DioErrorType.SEND_TIMEOUT:
          {
            return ErrorEntity(code: -1, message: "请求超时");
          }
          break;
        case DioErrorType.RECEIVE_TIMEOUT:
          {
            return ErrorEntity(code: -1, message: "响应超时");
          }
          break;
        case DioErrorType.RESPONSE:
          {
            try {
              int errCode = error.response.statusCode;
              String errMsg = error.response.statusMessage;
              // return ErrorEntity(code: errCode, message: errMsg);
              switch (errCode) {
                case 400:
                  {
                    return ErrorEntity(code: errCode, message: "请求语法错误");
                  }
                  break;
                case 403:
                  {
                    return ErrorEntity(code: errCode, message: "服务器拒绝执行");
                  }
                  break;
                case 404:
                  {
                    return ErrorEntity(code: errCode, message: "无法连接服务器");
                  }
                  break;
                case 405:
                  {
                    return ErrorEntity(code: errCode, message: "请求方法被禁止");
                  }
                  break;
                case 500:
                  {
                    return ErrorEntity(code: errCode, message: "服务器内部错误");
                  }
                  break;
                case 502:
                  {
                    return ErrorEntity(code: errCode, message: "无效的请求");
                  }
                  break;
                case 503:
                  {
                    return ErrorEntity(code: errCode, message: "服务器挂了");
                  }
                  break;
                case 505:
                  {
                    return ErrorEntity(code: errCode, message: "不支持HTTP协议请求");
                  }
                  break;
                default:
                  {
                    return ErrorEntity(code: errCode, message: "未知错误");
                  }
              }
            } on Exception catch (_) {
              return ErrorEntity(code: -1, message: "未知错误");
            }
          }
          break;
        default:
          {
            return ErrorEntity(code: -1, message: error.message);
          }
      }
    }
  }
}
